﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Drawing;
using DevExpress.XtraEditors.ViewInfo;
using System.Data;
using System.Collections;
using System.Drawing;

namespace ProgNetComponentsDx.Controls.Editors
{
    public class FilterableCheckedListBoxControl : CheckedListBoxControl
    {
        TextEdit edFilterEdit = new TextEdit();
        List<object> checkedObjects = new List<object>();

        public FilterableCheckedListBoxControl()
        {
            edFilterEdit.Name = "edFilterEdit";
            edFilterEdit.Dock = System.Windows.Forms.DockStyle.Top;
            this.Controls.Add(edFilterEdit);
        }
        protected override void OnLoaded()
        {
            base.OnLoaded();
            edFilterEdit.EditValueChanged += new EventHandler(edFilterEdit_EditValueChanged);

        }
        protected override void OnSetItemCheckState(DevExpress.XtraEditors.Controls.ItemCheckingEventArgs e)
        {
            base.OnSetItemCheckState(e);
            if (e.NewValue == System.Windows.Forms.CheckState.Checked)
            {
                checkedObjects.AddIfNotExist(GetItemValue(e.Index));
            }
            else
            {
                checkedObjects.Remove(GetItemValue(e.Index));
            }
        }
        private void SetCheckedItems()
        {
            for (int i = 0; i < ItemCount; i++)
            {
                if (checkedObjects.Contains(GetItemValue(i)))
                    SetItemChecked(i, true);
            }
        }
        void edFilterEdit_EditValueChanged(object sender, EventArgs e)
        {
            this.Refresh();
            SetCheckedItems();
        }

        public string Filter
        {
            get { return edFilterEdit.Text; }
            set { edFilterEdit.Text = value; }
        }
        public DevExpress.XtraGrid.Columns.AutoFilterCondition FilterCondition
        {
            get;
            set;
        }

        protected override DevExpress.XtraEditors.ViewInfo.BaseStyleControlViewInfo CreateViewInfo()
        {
            return new FilterableCheckListBoxViewInfo(this);
        }
    }

    public class FilterableCheckListBoxViewInfo : CheckedListBoxViewInfo
    {
        private int filteredCount;

        public FilterableCheckListBoxViewInfo(FilterableCheckedListBoxControl ctrl)
            : base(ctrl)
        {

        }

        private new FilterableCheckedListBoxControl OwnerControl
        {
            get { return base.OwnerControl as FilterableCheckedListBoxControl; }
        }

        protected override void CalcClientRect(System.Drawing.Rectangle bounds)
        {
            bounds = new System.Drawing.Rectangle(bounds.X, bounds.Y + 24, bounds.Width, bounds.Height - 24);

            base.CalcClientRect(bounds);
        }

        private int FilteredItemsCount
        {
            get
            {
                if (OwnerControl.Filter.IsNotNull())
                    return filteredCount;
                return ItemCount;
            }
        }

        private Hashtable myItemsInfo;

        protected override void CalcItemsInfo()
        {
            object obj = this.GetFieldValue("itemsInfo");
            myItemsInfo = obj as Hashtable;
            if (myItemsInfo == null || OwnerControl.Filter.IsNull())
            {
                base.CalcItemsInfo();
                return;
            }

            this.myItemsInfo.Clear();
            Rectangle bounds = Rectangle.Empty;
            if (this.OwnerControl.IsDesignMode && this.ItemCount == 0)
            {
                bounds = new Rectangle(this.ContentRect.Location, new Size(this.ContentRect.Width, this.ItemHeight));
                this.myItemsInfo.Add((object)0, (object)this.CalcItemInfo(bounds, -1));
            }
            else
            {
                filteredCount = 0;
                List<int> filtered = new List<int>();

                for (int topIndex = this.OwnerControl.TopIndex; topIndex < this.ItemCount; ++topIndex)
                {
                    if (IsMatch(OwnerControl.GetItemText(topIndex)))
                        filtered.Add(topIndex);
                }
                filteredCount = filtered.Count;
                CalcColumnsInfo();
                for (int topIndex = 0; topIndex < this.filteredCount; topIndex++)
                {
                    bounds = this.CalcItemBounds(topIndex, bounds.Bottom);
                    if (bounds.IsEmpty)
                        break;
                    else
                        this.myItemsInfo.Add((object)topIndex, (object)this.CalcItemInfo(bounds, filtered[topIndex]));
                }
            }
        }
        
        protected override int CalcColumnsCount(Rectangle contentRect)
        {
            if (!this.OwnerControl.MultiColumn)
            {
                return 1;
            }
            else
            {
                int num1 = contentRect.Height / this.ItemHeight;
                if (num1 < 1)
                    num1 = 1;
                int num2 = this.FilteredItemsCount / num1;
                if (num2 * num1 < this.FilteredItemsCount)
                    ++num2;
                return num2;
            }
        }

        protected override int CalcItemsPerColumnCount()
        {
            if (this.OwnerControl.MultiColumn)
                return Math.Max(1, this.ContentRect.Height / this.ItemHeight);
            else
                return this.FilteredItemsCount;
        }
        private bool IsMatch(string text)
        {
            switch (OwnerControl.FilterCondition)
            {
                case DevExpress.XtraGrid.Columns.AutoFilterCondition.Like:
                case DevExpress.XtraGrid.Columns.AutoFilterCondition.Default:
                    return text.StartsWith(OwnerControl.Filter, StringComparison.CurrentCultureIgnoreCase);
                case DevExpress.XtraGrid.Columns.AutoFilterCondition.Contains:
                    return text.ToUpper().Contains(OwnerControl.Filter.ToUpper());
                case DevExpress.XtraGrid.Columns.AutoFilterCondition.Equals:
                    return text.ToUpper() == OwnerControl.Filter.ToUpper();
            }
            return false;
        }
        public override int CalcBestColumnWidth()
        {
            int val1 = 0;
            try
            {
                Graphics g = this.GInfo.AddGraphics((Graphics)null);
                for (int index = 0; index < this.ItemCount; ++index)
                {
                    string itemText = this.OwnerControl.GetItemText(index);
                    if (IsMatch(itemText))
                        val1 = Math.Max(val1, this.PaintAppearance.CalcTextSize(g, itemText, 0).ToSize().Width);
                }
                val1 += this.ListBoxItemPainter.GetHorzPadding(this.ListBoxItemInfoArgs);
            }
            finally
            {
                this.GInfo.ReleaseGraphics();
            }
            if (val1 != 0)
                return val1 + 5;
            else
                return this.ContentRect.Width;
        }

        protected override bool CalcVScrollVisibility(Rectangle bounds)
        {
            if (this.OwnerControl.TopIndex > 0)
                return true;
            else if (bounds.Width <= ListBoxScrollInfo.DefaultVScrollWidth)
            {
                return false;
            }
            else
            {
                int num = 0;
                for (int itemIndex = 0; itemIndex < this.FilteredItemsCount; ++itemIndex)
                {
                    num += this.CalcItemSize(itemIndex, false).Height;
                    if (num > bounds.Height)
                        return true;
                }
                return false;
            }
        }

    }
}


